package devcken.springframework.web.multipart;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.commons.fileupload.FileItem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

/**
 * 다중 업로드를 지원하기 위한 멀티파트 요청을 분석한다. 
 * @author Devcken
 */
public class MultipleFileSupportMultipartResolver extends CommonsMultipartResolver
{
	private static final Logger logger = LoggerFactory.getLogger(MultipleFileSupportMultipartResolver.class);
	
	/**
	 * 업로드 최상위 디렉토리 경로(서버 측 로컬 경로)를 나타낸다.
	 */
	private static String UploadRootDirectory;

	/**
	 * 파일 목록을 분석한다.
	 * @param fileItems 공용 파일 목록
	 * @param encoding 파일 전송을 위해 이용된 폼 필드의 인코딩
	 * @return 멀티파트 분석 결과로 HTTP 요청에 대한 컨트롤러로 전달된다.
	 */
	@Override
	protected MultipartParsingResult parseFileItems(List<FileItem> fileItems, String encoding)
	{
		MultiValueMap<String, MultipartFile> multipartFiles = new LinkedMultiValueMap<String, MultipartFile>();
		Map<String, String[]> multipartParameters = new HashMap<String, String[]>();
		Map<String, String> parametersContentTypes = new HashMap<String, String>();
		
		try
		{
			for (Iterator<FileItem> iterator = fileItems.iterator(); iterator.hasNext();)
			{
				FileItem item = (FileItem)iterator.next();
				
				parametersContentTypes.put(item.getFieldName(), item.getContentType());
				
				// 폼 필드인 경우 그에 대한 값을 가져와 멀티파트 파라메터로 설정한다.
				if (item.isFormField())
				{
					String value = null;
					
					if (encoding != null)
					{
						try
						{
							value = item.getString(encoding);
						}
						catch (UnsupportedEncodingException error)
						{
							value = item.getString();
						}
					}
					else
					{
						value = item.getString();
					}
					
					String[] currentParameter = (String[])multipartParameters.get(item.getFieldName());
					
					if (currentParameter == null)
					{
						multipartParameters.put(item.getFieldName(), new String[] {value});
					}
					else
					{
						String[] newParameter = StringUtils.addStringToArray(currentParameter, value);
						
						multipartParameters.put(item.getFieldName(), newParameter);
					}
				}
				// 업로드 파일인 경우, 그에 대한 파일 정보를 가져와 멀티파트 파일로 설정한다.
				else
				{
					CommonsMultipartFile file = new CommonsMultipartFile(item);
					
					List<MultipartFile> files = multipartFiles.get(item.getFieldName());
					
					if (files == null)
					{
						files = new LinkedList<MultipartFile>();
						
						files.add(file);
						
						multipartFiles.put(item.getFieldName(), files);
					}
					else
					{
						files.add(file);
					}
				}
			}
		}
		catch (Exception error)
		{
			logger.error(error.getMessage(), error);
		}

		return new MultipartParsingResult(multipartFiles, multipartParameters, parametersContentTypes);
	}

	public static String getUploadRootDirectory()
	{
		return MultipleFileSupportMultipartResolver.UploadRootDirectory;
	}

	public void setUploadRootDirectory(String uploadRootDirectory)
	{
		MultipleFileSupportMultipartResolver.UploadRootDirectory = uploadRootDirectory;
	}
}